package jenetics.test;

import org.jenetics.DoubleChromosome;
import org.jenetics.DoubleGene;
import org.jenetics.Genotype;
import org.jenetics.MeanAlterer;
import org.jenetics.Mutator;
import org.jenetics.Optimize;
import org.jenetics.Phenotype;
import org.jenetics.engine.Engine;
import org.jenetics.engine.EvolutionStatistics;

import static java.lang.Math.cos;
import static java.lang.Math.sin;
import static java.lang.Math.PI;
import static org.jenetics.engine.limit.bySteadyFitness;
import static org.jenetics.engine.EvolutionResult.toBestPhenotype;

public class RealFunction {

	public static void main(String[] args) {
		final Engine<DoubleGene, Double> engine = 
				Engine.builder(RealFunction::eval, DoubleChromosome.of(0.0, 2.0 * PI)).populationSize(500).optimize(Optimize.MINIMUM).alterers(new Mutator<>(0.03), new MeanAlterer<>(0.6)).build();
		
		final EvolutionStatistics<Double, ?> statistics = EvolutionStatistics.ofNumber();
		
		final Phenotype<DoubleGene, Double> best = engine.stream().limit(bySteadyFitness(7)).limit(100).peek(statistics).collect(toBestPhenotype());
		
		System.out.println(statistics);
		System.out.println(best);
	}

	private static Double eval(final Genotype<DoubleGene> gt) {
		final double x = gt.getGene().doubleValue();
		return cos(0.5 + sin(x)) * cos(x);
	}
	
}